#ifndef __KERNEL_CPUMASK_H_
#define __KERNEL_CPUMASK_H_

#include <utils/cpumask.h>

#if CONFIG_NR_CPUS == 1
#define nr_cpu_ids		1U
#else
extern int nr_cpu_ids;
#endif

#define cpumask_pr_args(maskp)		nr_cpu_ids, cpumask_bits(maskp)

extern struct cpumask __cpu_possible_mask;
extern struct cpumask __cpu_online_mask;
#define cpu_possible_mask ((const struct cpumask *)&__cpu_possible_mask)
#define cpu_online_mask   ((const struct cpumask *)&__cpu_online_mask)

#if CONFIG_NR_CPUS > 1
#define num_online_cpus()	cpumask_weight(cpu_online_mask)
#define num_possible_cpus()	cpumask_weight(cpu_possible_mask)
#define cpu_online(cpu)		cpumask_test_cpu((cpu), cpu_online_mask)
#define cpu_possible(cpu)	cpumask_test_cpu((cpu), cpu_possible_mask)
#else
#define num_online_cpus()	1U
#define num_possible_cpus()	1U
#define cpu_online(cpu)		((cpu) == 0)
#define cpu_possible(cpu)	((cpu) == 0)
#endif

/* It's common to want to use cpu_all_mask in struct member initializers,
 * so it has to refer to an address rather than a pointer. */
extern const DECLARE_BITMAP(cpu_all_bits, CONFIG_NR_CPUS);
#define cpu_all_mask to_cpumask(cpu_all_bits)

/* First bits of cpu_bit_bitmap are in fact unset. */
#define cpu_none_mask to_cpumask(cpu_bit_bitmap[0])

#define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)
#define for_each_online_cpu(cpu)   for_each_cpu((cpu), cpu_online_mask)

static inline void
set_cpu_possible(unsigned int cpu, bool possible)
{
    if (possible)
        cpumask_set_cpu(cpu, &__cpu_possible_mask);
    else
        cpumask_clear_cpu(cpu, &__cpu_possible_mask);
}

static inline void
set_cpu_online(unsigned int cpu, bool online)
{
    if (online)
        cpumask_set_cpu(cpu, &__cpu_online_mask);
    else
        cpumask_clear_cpu(cpu, &__cpu_online_mask);
}

#define cpu_is_offline(cpu)	unlikely(!cpu_online(cpu))

/*
 * Special-case data structure for "single bit set only" constant CPU masks.
 *
 * We pre-generate all the 64 (or 32) possible bit positions, with enough
 * padding to the left and the right, and return the constant pointer
 * appropriately offset.
 */
extern const unsigned long
    cpu_bit_bitmap[BITS_PER_LONG + 1][BITS_TO_LONGS(CONFIG_NR_CPUS)];

static inline int __check_is_bitmap(const unsigned long *bitmap)
{
    return 1;
}

/**
 * to_cpumask - convert an CONFIG_NR_CPUS bitmap to a struct cpumask *
 * @bitmap: the bitmap
 *
 * There are a few places where cpumask_var_t isn't appropriate and
 * static cpumasks must be used (eg. very early boot), yet we don't
 * expose the definition of 'struct cpumask'.
 *
 * This does the conversion, and can be used as a constant initializer.
 */
#define to_cpumask(bitmap)						\
    ((struct cpumask *)(1 ? (bitmap)				\
                : (void *)sizeof(__check_is_bitmap(bitmap))))

static inline const struct cpumask *get_cpu_mask(int cpu)
{
    const unsigned long *p = cpu_bit_bitmap[1 + cpu % BITS_PER_LONG];
    p -= cpu / BITS_PER_LONG;
    return to_cpumask(p);
}

/**
 * cpumask_of - the cpumask containing just a given cpu
 * @cpu: the cpu (<= nr_cpu_ids)
 */
#define cpumask_of(cpu) (get_cpu_mask(cpu))

#endif /* !__KERNEL_CPUMASK_H_ */
